package com.zimi.file.service;

import com.zimi.file.exception.InvalidExtensionException;
import com.zimi.file.mapper.SysFileMapper;
import com.zimi.file.model.SysFile;
import com.zimi.util.FileUtils;
import com.zimi.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


@Slf4j
@Service
public class FileInfoService {

    private final SysFileMapper sysFileMapper;

    @Value("${zimi.profile:file}")
    private String basePath;

    @Autowired
    public FileInfoService(SysFileMapper sysFileMapper) {
        this.sysFileMapper = sysFileMapper;
    }

    /**
     * 上传文件
     *
     * @param file 文件
     */
    @Transactional
    public Object upload(MultipartFile file) throws InvalidExtensionException {
        String originalFilename = file.getOriginalFilename();
        String fileName = FileUtils.getFileName() + FileUtils.getFileNameSub(Objects.requireNonNull(originalFilename));
        String folder = FileUtils.getFolder();
        Map<String, Object> map = new HashMap<>();
        boolean ckName = originalFilename.matches("^(?!.*?[/:*?<>|]).*$");
        if (!ckName) {
            map.put("id", -1);
            map.put("code", 405);
            map.put("msg", "upload error");
            map.put("info", "原文件名不被允许\n请检查上传的文件名\t不允许包含以下任何字符'/',':','*','?','<','>','|'");
            return map;
        }
        if (null == UserUtil.getUser().getId()) return "请先登录后操作文件";
        try {
            Path filePath = Files.createDirectories(Paths.get(basePath, folder));
            Path fullPath = Paths.get(basePath, folder, fileName);
            Files.write(fullPath, file.getBytes(), StandardOpenOption.CREATE);
            SysFile sysFile = new SysFile();
            sysFile.setFileOriginName(originalFilename);
            sysFile.setFileType(file.getContentType());
            sysFile.setSize(file.getSize());
            sysFile.setMd5(FileUtils.md5File(fullPath.toString()));
            sysFile.setFileName(fileName);
            sysFile.setFilePath(filePath.toString());
            sysFile.setUploadUser(UserUtil.getUser().getId());
            sysFile.setUploadTime(new Date());
            sysFile.insert();
            map.put("id", sysFile.getId());
            map.put("msg", "upload success");
            map.put("code", 200);
            map.put("info", file);
            return map;
        } catch (Exception e) {
            Path path = Paths.get(basePath, folder, fileName);
            log.error("写入文件异常,删除文件。。。。", e);
            try {
                Files.deleteIfExists(path);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            map.put("id", -1);
            map.put("code", 500);
            map.put("msg", "upload error");
            map.put("info", "上传失败\n检查文件是否过大,以及网络是否通畅");
            return map;
        }
    }

    /**
     * 文件下载
     *
     * @param id
     * @param res
     * @throws UnsupportedEncodingException
     * @throws InvalidExtensionException
     */
    @Transactional
    public void downloadFile(Integer id, HttpServletResponse res) throws UnsupportedEncodingException, InvalidExtensionException {
        SysFile fileInfo = sysFileMapper.selectByPrimaryKey(id);
        String fileName = fileInfo.getFileName();
        //设置响应头
        res.setContentType("application/force-download");// 设置强制下载不打开
        res.addHeader("Content-Disposition", "attachment;fileName=" +
                new String(fileInfo.getFileOriginName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));// 设置文件名
        res.setHeader("Context-Type", "application/xmsdownload");

        //判断文件是否存在
        File file = new File(String.valueOf(Paths.get(fileInfo.getFilePath(), fileInfo.getFileName())));
        if (file.exists()) {
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            OutputStream os = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                os = res.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
                //log.info("下载成功");
            } catch (Exception e) {
                throw new InvalidExtensionException(null, e.getMessage(), fileName);
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 文件查看
     */
    public SysFile viewFile(Integer id) throws IOException {
        SysFile fileInfo = sysFileMapper.selectByPrimaryKey(id);
        if (fileInfo == null) {
            return null;
        }
        Path path = Paths.get(fileInfo.getFilePath(), fileInfo.getFileName());
        fileInfo.setContent(Files.newInputStream(path));
        return fileInfo;
    }

    /**
     * 文件查看
     */
    public SysFile assets(String filepath, String filename) throws IOException {
        SysFile fileInfo = new SysFile();
        Path path = Paths.get(filepath, filename);
        fileInfo.setContent(Files.newInputStream(path));
        return fileInfo;
    }

    /**
     * 根据资源id查询文件信息
     *
     * @return
     */
    public Object findFileList(Integer id) throws InvalidExtensionException {
        if (id == null) {
            throw new InvalidExtensionException(null, "资源id不能为空", null);
        }
        // 根据资源id查询文件信息
        return sysFileMapper.selectByPrimaryKey(id);
    }


    /**
     * 删除文件
     *
     * @param id
     * @return
     */
    public Object deleteFile(int id) throws InvalidExtensionException {
        SysFile fileInfo = sysFileMapper.selectByPrimaryKey(id);
        String fileName = fileInfo.getFileName();
        String filePath = fileInfo.getFilePath();
        String folder = filePath.substring(filePath.lastIndexOf("\\"));
        if (fileName == null) {
            throw new InvalidExtensionException(null, "文件不存在", null);
        }
        //删除数据库数据
        sysFileMapper.deleteByPrimaryKey(id);
        //删除物理文件
        Path path = Paths.get(basePath, folder, fileName);
        try {
            Files.deleteIfExists(path);

        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return true;
    }

    /**
     * 每天执行一次,清除无效图片
     */
    @Scheduled(cron = "0 0 0 1/1 * ? ")
    public void deleteValidFalse() {
        //定时删除无效图片信息
        //List<FileInfo> fileInfos = mapper.findByValid(false);
        //mapper.deleteAll(fileInfos);
        //log.info("本次删除数据:{}", fileInfos);
    }

}
